<!--<template>-->
<!--    <a-modal width="95vw"-->
<!--             size="small"-->
<!--             ref="modalRef"-->
<!--             style="top: 20px"-->
<!--             v-model:open="webConfig.isOpenAi" :wrap-style="{ overflow: 'hidden' }" @ok="handleOk">-->
<!--      <div style="width: 100%;height: 70vh">-->
<!--        <div class="ai">-->
<!--          <a-layout style="width: 100%;height: 100%;position: relative;margin: 5px;border-radius: 8px;overflow: hidden">-->
<!--            <a-layout-sider :width="leftWidth" style="position: absolute;top: 0;bottom: 0;" theme="light"  v-model:collapsed="collapsed" >-->
<!--              <a-menu style="width: 100%;position: absolute;bottom: 0;top: 0;overflow-y:scroll;"-->
<!--                      v-model:selectedKeys="selectedKeys" theme="light" mode="inline">-->
<!--                <div style="margin: 10px;height: 40px;display: flex;align-items: center;justify-content: center">-->
<!--                  <a-button @click="newAi" style="width: 100%">-->
<!--                    新建-->
<!--                  </a-button>-->
<!--                </div>-->
<!--                <a-menu-item v-for="item in sides" :key="item.key">-->
<!--                  <CommentOutlined />-->
<!--                  <span>{{item.title}}</span>-->
<!--                </a-menu-item>-->
<!--              </a-menu>-->
<!--              &lt;!&ndash;          <div style="position: absolute;border-right-width: 1px;border-color : #7e8c8d;bottom: 0px;width: 100%;height: 40px;display: flex;align-items: center;justify-content: center">&ndash;&gt;-->
<!--              &lt;!&ndash;            <PieChartOutlined/>&ndash;&gt;-->
<!--              &lt;!&ndash;          </div>&ndash;&gt;-->
<!--            </a-layout-sider>-->
<!--            <a-layout>-->
<!--              <a-layout-content :style="layoutStyle">-->
<!--                <div class="comment-list">-->
<!--                  <a-list-->
<!--                      v-if="comments.length"-->
<!--                      :data-source="comments"-->
<!--                      item-layout="horizontal"-->
<!--                  >-->
<!--                    <template #renderItem="{ item }">-->
<!--                      <a-list-item>-->
<!--                        <a-comment-->
<!--                            :author="item.author"-->
<!--                            avatar="http://image.xlfdeblog.top/blog/6f01ea57bbcb910fd452f684f4305019.jpg"-->
<!--                            :content="item.content"-->
<!--                            :datetime="item.datetime"-->
<!--                        />-->
<!--                      </a-list-item>-->
<!--                    </template>-->
<!--                  </a-list>-->
<!--                  <a-comment>-->
<!--                    <template #avatar>-->
<!--                      <a-avatar src="http://image.xlfdeblog.top/blog/6f01ea57bbcb910fd452f684f4305019.jpg" alt="Han Solo" />-->
<!--                    </template>-->
<!--                    <template #content>-->
<!--                      <a-form-item>-->
<!--                        <a-textarea v-model:value="value" :rows="4" />-->
<!--                      </a-form-item>-->
<!--                      <a-form-item>-->
<!--                        <a-button html-type="submit" :loading="submitting" type="primary" @click="handleSubmit">-->
<!--                          Add Comment-->
<!--                        </a-button>-->
<!--                      </a-form-item>-->
<!--                    </template>-->
<!--                  </a-comment>-->
<!--                </div>-->
<!--              </a-layout-content>-->
<!--            </a-layout>-->
<!--          </a-layout>-->
<!--        </div>-->
<!--      </div>-->
<!--      <template #title>-->
<!--        <div ref="modalTitleRef" style="width: 100%; cursor: move">NO 知道</div>-->
<!--      </template>-->
<!--      <template #modalRender="{ originVNode }">-->
<!--        <div :style="transformStyle">-->
<!--          <component :is="originVNode" />-->
<!--        </div>-->
<!--      </template>-->
<!--    </a-modal>-->

<!--</template>-->
<!--<script lang="ts" setup>-->
<!--import useStore from "@/store";-->
<!--const {webConfig} = useStore()-->
<!--const collapsed = ref<boolean>(false);-->
<!--const selectedKeys = ref<number[]>([1]);-->
<!--const leftWidth = ref(180)-->
<!--import type { CSSProperties } from 'vue';-->
<!--const layoutStyle: CSSProperties = {-->
<!--  marginLeft: '180px',-->
<!--  height: '100%'-->
<!--};-->
<!--import dayjs from 'dayjs';-->
<!--import {CommentOutlined} from '@ant-design/icons-vue';-->
<!--import relativeTime from 'dayjs/plugin/relativeTime';-->
<!--dayjs.extend(relativeTime);-->
<!--const comments = [-->
<!--  {-->
<!--    author:'role',-->
<!--    avatar:"https://joeschmoe.io/api/v1/random",-->
<!--    createTime:"",-->
<!--    content:"We supply a series of design principles, practical patterns and high quality design\n" +-->
<!--        "                    resources (Sketch and Axure), to help people create their product prototypes beautifully and\n" +-->
<!--        "                    efficiently.",-->
<!--    datetime:"2024-01-29 11:30:33"-->
<!--  },-->
<!--  {-->
<!--    author:'role',-->
<!--    avatar:"https://joeschmoe.io/api/v1/random",-->
<!--    createTime:"",-->
<!--    content:"We supply a series of design principles, practical patterns and high quality design\n" +-->
<!--        "                    resources (Sketch and Axure), to help people create their product prototypes beautifully and\n" +-->
<!--        "                    efficiently.",-->
<!--    datetime:"2024-01-29 11:30:33"-->
<!--  },-->
<!--  {-->
<!--    author:'role',-->
<!--    avatar:"https://joeschmoe.io/api/v1/random",-->
<!--    createTime:"",-->
<!--    content:"We supply a series of design principles, practical patterns and high quality design\n" +-->
<!--        "                    resources (Sketch and Axure), to help people create their product prototypes beautifully and\n" +-->
<!--        "                    efficiently.",-->
<!--    datetime:"2024-01-29 11:30:33"-->
<!--  },-->

<!--]-->
<!--const sides = reactive([-->
<!--  {-->
<!--    key:1,-->
<!--    title:"窗口1"-->
<!--  },-->
<!--])-->

<!--const newAi = () => {-->
<!--  const timestamp = Date.now();-->
<!--  sides.push({-->
<!--    key:timestamp,-->
<!--    title: "窗口" + (sides.length + 1)-->
<!--  })-->
<!--}-->

<!--import { useDraggable } from '@vueuse/core';-->
<!--import SvgIcon from "@/components/SvgIcon/index.vue";-->
<!--const modalTitleRef = ref<HTMLElement>(null);-->
<!--const showModal = () => {-->
<!--  webConfig.aiOper()-->
<!--};-->
<!--const { x, y, isDragging } = useDraggable(modalTitleRef);-->
<!--const handleOk = (e: MouseEvent) => {-->
<!--  webConfig.aiOper()-->
<!--};-->
<!--const startX = ref<number>(0);-->
<!--const startY = ref<number>(0);-->
<!--const startedDrag = ref(false);-->
<!--const transformX = ref(0);-->
<!--const transformY = ref(0);-->
<!--const preTransformX = ref(0);-->
<!--const preTransformY = ref(0);-->
<!--const dragRect = ref({ left: 0, right: 0, top: 0, bottom: 0 });-->
<!--watch([x, y], () => {-->
<!--  if (!startedDrag.value) {-->
<!--    startX.value = x.value;-->
<!--    startY.value = y.value;-->
<!--    const bodyRect = document.body.getBoundingClientRect();-->
<!--    const titleRect = modalTitleRef.value.getBoundingClientRect();-->
<!--    dragRect.value.right = bodyRect.width - titleRect.width;-->
<!--    dragRect.value.bottom = bodyRect.height - titleRect.height;-->
<!--    preTransformX.value = transformX.value;-->
<!--    preTransformY.value = transformY.value;-->
<!--  }-->
<!--  startedDrag.value = true;-->
<!--});-->
<!--watch(isDragging, () => {-->
<!--  if (!isDragging) {-->
<!--    startedDrag.value = false;-->
<!--  }-->
<!--});-->

<!--watchEffect(() => {-->
<!--  if (startedDrag.value) {-->
<!--    transformX.value =-->
<!--        preTransformX.value +-->
<!--        Math.min(Math.max(dragRect.value.left, x.value), dragRect.value.right) - -->
<!--        startX.value;-->
<!--    transformY.value =-->
<!--        preTransformY.value +-->
<!--        Math.min(Math.max(dragRect.value.top, y.value), dragRect.value.bottom) - -->
<!--        startY.value;-->
<!--  }-->
<!--});-->
<!--const transformStyle = computed<CSSProperties>(() => {-->
<!--  return {-->
<!--    transform: `translate(${transformX.value}px, ${transformY.value}px)`,-->
<!--  };-->
<!--});-->

<!--</script>-->
<!--<style scoped lang="scss">-->
<!--//@import "src/assets/base";-->
<!--//-->
<!--//#components-layout-demo-side .logo {-->
<!--//  height: 32px;-->
<!--//  margin: 16px;-->
<!--//  background: rgba(255, 255, 255, 0.3);-->
<!--//}-->
<!--//-->
<!--//.site-layout .site-layout-background {-->
<!--//  background: #fff;-->
<!--//}-->
<!--//[data-theme='dark'] .site-layout .site-layout-background {-->
<!--//  background: #141414;-->
<!--//}-->
<!--//-->
<!--//@include a-card-flex;-->

<!--.ai{-->
<!--  width: 100%;-->
<!--  height: 100%;-->
<!--  .comment-list{-->
<!--    padding: 15px;-->
<!--    overflow-y: scroll;-->
<!--    height: 100%;-->
<!--  }-->

<!--}-->
<!--</style>-->



<template>
  <a-modal width="80vw"
           size="small"
           ref="modalRef"
           style="top: 20px"
           :footer="false"
           v-model:open="webConfig.isOpenAi" :wrap-style="{ overflow: 'hidden' }" @ok="handleOk">
    <div style="width: 100%;height: 80vh">
      <div class="ai">
        <a-tabs style="height: 100%;width: 100%" size="small"  v-model:activeKey="chatStore.active" type="editable-card" @edit="onEdit">
          <a-tab-pane  v-for="pane in panes" :key="pane.uuid" :tab="pane.title" :closable="pane.closable">
            <div ref="useScroll" class="comment-list">
              <a-list
                  :data-source="data"
                  item-layout="horizontal"
              >
                <template #renderItem="{ index,item }">
                  <a-list-item>
                    <a-comment
                        :author="item.role == 'user' ? user.name : 'AI'"
                        :avatar="item.role == 'user' ? user.avatar : 'http://image.xlfdeblog.top/blog/6f01ea57bbcb910fd452f684f4305019.jpg'"
                        :datetime="$dataUtils.parseTime(item.dateTime)"
                    >
                      <template #content>
                       <chat-message :role="item.role"
                                     ref="'message-'{{index}}"
                                     :content="item.text"/>
                      </template>
                    </a-comment>
                  </a-list-item>
                </template>
              </a-list>
            </div>
          </a-tab-pane>
        </a-tabs>
       <div class="chat-input">
         <a-flex style="height: 40px;" wrap="wrap" :gap="10" align="center" justify="flex-center">
           <a-avatar  :src="user.avatar"  />
           <a-textarea rows="1" style="flex: 1" v-model:value="content" />
           <a-button html-type="submit" :loading="submitting" type="primary" @click="handleSubmitStream">
             发送
           </a-button>
         </a-flex>
       </div>
      </div>
    </div>
    <template #title>
      <div ref="modalTitleRef" style="width: 100%; cursor: move">NO 知道</div>
    </template>
    <template #modalRender="{ originVNode }">
      <div :style="transformStyle">
        <component :is="originVNode" />
      </div>
    </template>
  </a-modal>

</template>
<script lang="ts" setup>
import useStore from "@/store";
import { NativeEventSource, EventSourcePolyfill } from 'event-source-polyfill';
const {webConfig,user,chatStore} = useStore()

import type { CSSProperties } from 'vue';
import {getToken} from "@/utils/auth"
import ChatMessage from "./ChatMessage"
const content = ref<string>()
const submitting = ref<boolean>(false)
onMounted(() => {
})
const initStream = () => {

  let lastText = ''
  const eventSource = new EventSourcePolyfill('/api/ai/stream/connect', {
    headers: {
      'Authorization': getToken()
    }
  });
  /*
    * open：订阅成功（和后端连接成功）
    */
  eventSource.addEventListener("open", function(e) {
    // console.log(e)
    console.log('open successfully')
  })
  /*
  * message：后端返回信息，格式可以和后端协商
  */
  eventSource.addEventListener("msg", function(e) {
    const t = JSON.parse(e.data);
    // console.log(t)
    // console.log(chatStore.active)
    chatStore.updateLastChatByUuid(
        t.chatId,
        {
          dateTime: new Date().toLocaleString(),
          text: lastText + t.result,
          inversion: false,
          error: false,
          loading: t.isEnd == 0
        },
    )
    lastText = lastText + t.result;
    if(t.isEnd == 1){
      submitting.value = false;
      eventSource.close()
    }
    const commentList = document.getElementsByClassName("ant-tabs-content-holder")
    console.log("commentList")
    console.log(commentList)
    if(commentList && commentList.length > 0)
      scrollToBottom(document.getElementsByClassName("ant-tabs-content-holder")[0])
  })
  /*
  * error：错误（可能是断开，可能是后端返回的信息）
  */
  eventSource.addEventListener("error", function(err) {
    console.log(err)
    eventSource.close()
  })

}
function scrollToBottom(element) {
  element.scrollTop = element.scrollHeight;
}
const panes = computed(() => chatStore.history)
const data = computed(() => chatStore.getChatByUuid(activeKey.value))
const activeKey = computed({
  get : () => {chatStore.active},
  set : (uuid) => {chatStore.setActive(uuid)}
});
const add = () => {
  const t = Date.now();
  const newHistory = {
    title : "New Chat",
    uuid : t,
    isEdit : true
  } as Chat.History
  chatStore.addHistory(newHistory)
};
const remove = (uuid: number) => {
  chatStore.deleteHistory(uuid)
};
const onEdit = (targetKey: number , action: string) => {
  if (action === 'add') {
    add();
  } else {
    remove(targetKey);
  }
};

/**
 * 非流式
 */
const handleSubmit = async () => {

  submitting.value = true;
  const data = {
    content : content.value,
    chatId : activeKey.value
  }
  chatStore.addChatByUuid(
      chatStore.active,
      {
        dateTime: new Date().toLocaleString(),
        text: content.value,
        role: 'user',
        error: false,
        conversationOptions: null,
        requestOptions: { prompt: content.value, options: null },
      } as Chat.Chat,
  )

  content.value = ''

  try {
    const res = await chatSingle(data)
    chatStore.addChatByUuid(
        chatStore.active,
        {
          dateTime: new Date().toLocaleString(),
          text: res.data,
          role: 'assistant',
          error: false,
          conversationOptions: null,
          requestOptions: { prompt: content.value, options: null },
        } as Chat.Chat,
    )
  } catch (e) {
    chatStore.addChatByUuid(
        chatStore.active,
        {
          dateTime: new Date().toLocaleString(),
          text: e,
          role: 'assistant',
          error: true,
          conversationOptions: null,
          requestOptions: { prompt: content.value, options: null },
        } as Chat.Chat,
    )
  } finally {
    submitting.value = false;

  }

}


/**
 * 流式
 */
const handleSubmitStream = async () => {

  submitting.value = true;

  chatStore.addChatByUuid(
      chatStore.active,
      {
        dateTime: new Date().toLocaleString(),
        text: content.value,
        role: 'user',
        error: false,
        loading:true,
        conversationOptions: null,
        requestOptions: { prompt: content.value, options: null },
      } as Chat.Chat,
  )

  chatStore.addChatByUuid(
      chatStore.active,
      {
        dateTime: new Date().toLocaleString(),
        text: '',
        role: 'assistant',
        error: false,
        loading:false,
        conversationOptions: null,
        requestOptions: { prompt: content.value, options: null },
      } as Chat.Chat,
  )

  const params = {
    content : content.value,
    chatId : chatStore.active
  }
  content.value = ''
  try {
    initStream();
    await chatSingleOfStream(params)
    submitting.value = false;
  } catch (e) {

  } finally {

  }

}


import { useDraggable } from '@vueuse/core';
import {message} from "ant-design-vue";
import {chatSingle, chatSingleOfStream} from "@/api/ai";
import {sseService} from "@/utils/SSEChatUtils";
import {getJudgeProblemResult} from "@/api/judge";
const modalTitleRef = ref<HTMLElement>(null);
const showModal = () => {
  webConfig.aiOper()
};
const { x, y, isDragging } = useDraggable(modalTitleRef);
const handleOk = (e: MouseEvent) => {
  webConfig.aiOper()
};
const startX = ref<number>(0);
const startY = ref<number>(0);
const startedDrag = ref(false);
const transformX = ref(0);
const transformY = ref(0);
const preTransformX = ref(0);
const preTransformY = ref(0);
const dragRect = ref({ left: 0, right: 0, top: 0, bottom: 0 });
watch([x, y], () => {
  if (!startedDrag.value) {
    startX.value = x.value;
    startY.value = y.value;
    const bodyRect = document.body.getBoundingClientRect();
    const titleRect = modalTitleRef.value.getBoundingClientRect();
    dragRect.value.right = bodyRect.width - titleRect.width;
    dragRect.value.bottom = bodyRect.height - titleRect.height;
    preTransformX.value = transformX.value;
    preTransformY.value = transformY.value;
  }
  startedDrag.value = true;
});
watch(isDragging, () => {
  if (!isDragging) {
    startedDrag.value = false;
  }
});

watchEffect(() => {
  if (startedDrag.value) {
    transformX.value =
        preTransformX.value +
        Math.min(Math.max(dragRect.value.left, x.value), dragRect.value.right) -
        startX.value;
    transformY.value =
        preTransformY.value +
        Math.min(Math.max(dragRect.value.top, y.value), dragRect.value.bottom) -
        startY.value;
  }
});
const transformStyle = computed<CSSProperties>(() => {
  return {
    transform: `translate(${transformX.value}px, ${transformY.value}px)`,
  };
});

</script>
<style scoped lang="scss">
@import "src/assets/base";
.ai{
  width: 100%;
  height: 100%;
  position: relative;
  .comment-list{
    padding: 5px;
    padding-bottom: 50px;
    overflow-y: scroll;
  }

  .chat-input{
    width: calc(100% - 20px);
    margin: 0 10px;
    position: absolute;
    bottom: 0;
  }

}
</style>


